#include"msgnum.h"

#define DB_PATH "./sq.db"
#define SQL_LEN 128

void main_func();
int login_func();
void check_func();
void rev_func();
void add_func();
void del_func();
void list_func();

struct login logininfo;		//当前登录用户信息
struct MSG msg_get;			//接收到的命令消息
struct MSG msg_send;		//要发送的命令消息	
int serverfd,clientfd;	
char *revworda[6] = {"password='","name='","sex=","address='","phone='","money="};
char *revwordb[6] = {"' ","' "," ","' ","' "," "};

sqlite3 *db;
int recvnum,n_row;
char sql[SQL_LEN],**rep,*errmsg;

int main(int argc, const char *argv[])
{
	if(argc != 3)					//参数判断
	{
		puts("server <ip> <port>");
		return -1;
	}

	if(sqlite3_open(DB_PATH,&db) != SQLITE_OK)
	{
		puts("sql error");
		return -1;
	}

	socklen_t len=sizeof(SA);			//网络初始化
	
	struct sockaddr_in serveradd,clientadd;
	bzero(&serveradd,len);
	bzero(&clientadd,len);

	if((serverfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
		err_log("socket error");

	serveradd.sin_family 		= AF_INET;
	serveradd.sin_addr.s_addr 	= inet_addr(argv[1]);
	serveradd.sin_port			= htons(atoi(argv[2]));
	
	if(bind(serverfd,(SA*)&serveradd,len) < 0)
		err_log("bind error");

	if(listen(serverfd,5) < 0)
		err_log("listen error");
	
	while(1)   							//通信进程产生循环，二级fork 无需考虑回收
	{
		pid_t pid;
		if((clientfd = accept(serverfd,(SA*)&clientadd,&len)) < 0)
		{
			perror("accept error");
			continue;
		}

		if((pid = fork()) < 0)
		{
			perror("1st fork error");
			exit(1);
		}
		else if(pid == 0)
		{
			if((pid = fork()) < 0)
			{
				perror("2ed fork error");
				exit(1);
			}
			/****son****/
			else if(pid)
				exit(0);
			/****son end****/
			/****grandson****/
			main_func();
			return 0;
			/****grandson end****/
		}
		/****father****/
		if(waitpid(pid,NULL,0) != pid)
		{
			puts("waitpid error");
			exit(1);
		}
		/****father end****/
	}
	return 0;
}

void main_func()
{
	puts("main_func");

	int ret;
	while(1)					//登录循环
	{
RELOG:
		ret = login_func();
		if(ret < 0)
			return;				//主循环出口

		while(1)				//指令接收循环
		{
			recvnum = recv(clientfd,(void *)&msg_get,sizeof(msg_get),0);
			if(recvnum < 0)
			{
				puts("fail to recv");		//接收失败
				return ;
			}
			if(recvnum == 0)
			{
				puts("client exit");		//客户端退出 主循环出口
				close(clientfd);
				return ;
			}

			switch(msg_get.cmd)
			{
			case COM_SHOW:				//普通用户显示信息
				strcpy(msg_get.msg,logininfo.number);
				check_func();
				break;
			case ADM_SHOW:				//管理员查找显示信息
				check_func();
				break;
			case ADM_RVS:				//管理员修改信息
				rev_func();
				break;
			case ADM_ADD:				//管理员添加用户
				add_func();
				break;
			case ADM_DEL:				//管理员删除用户
				del_func();
				break;
			case ADM_LIST:				//管理员列举用户
				list_func();
				break;
			case BACK:					//退出到登录界面
				goto RELOG;				//指令循环出口
			default:					//普通用户修改信息
				rev_func();
			}
		}
	}
}

int login_func()						//登录函数
{
	puts("login");

	while(1)
	{
		recvnum = recv(clientfd,(void *)&logininfo,sizeof(logininfo),0);
		if(recvnum < 0)
		{
			puts("fail to recv");
			return -1;
		}
		if(recvnum == 0)
		{
			puts("client exit");
			close(clientfd);
			return -2;
		}
		
		sprintf(sql,"select * from stuff where number='%s'",logininfo.number);	//查找员工号
		if(sqlite3_get_table(db,sql,&rep,&n_row,NULL,&errmsg))
		{
			puts(errmsg);
			return;
		}

		if(n_row)		//有此员工号
		{					//权限检查
			if((((int)(*rep[SQ_NUM + SQ_POWER] - '0')) >= logininfo.flags)&&\
					(!(strcmp(rep[SQ_NUM + SQ_PASSWORD],logininfo.password))))				//密码检查
			{
				msg_send.cmd = OK;
				send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
				sqlite3_free_table(rep);
				break;
			}
			else 		//密码或权限不对
				msg_send.cmd = ERROR;
		}else   		//无此员工号
			msg_send.cmd = NO_USER;

		send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
		sqlite3_free_table(rep);
	}
}

void check_func()	//查找函数
{
	puts("check");

  	sprintf(sql,"select * from stuff where number='%s'",msg_get.msg);
	if(sqlite3_get_table(db,sql,&rep,&n_row,NULL,&errmsg))
	{
		puts(errmsg);
		return;
	}

	if(n_row)		//有此员工号
	{
		sprintf(msg_send.msg,"员工编号  姓名          权限   性别   地址        电话        工资\n  %-8s%-14s%-10s%-8s%-12s%-13s%-10s\n",\
				rep[SQ_NUM + SQ_NUMBER],rep[SQ_NUM + SQ_NAME],(*rep[SQ_NUM + SQ_POWER] == '1' ? "管理员" : "普通"),\
				(*rep[SQ_NUM + SQ_SEX] == '1' ? "男" : "女"),rep[SQ_NUM + SQ_ADDRESS],rep[SQ_NUM + SQ_PHONE],rep[SQ_NUM + SQ_MONEY]);		//信息打印
		msg_send.cmd = OK;

	}else   		//无此员工号
		msg_send.cmd = NO_USER;

	send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
	sqlite3_free_table(rep);
}

void rev_func()			//修改函数
{
	char number[NUM_LEN];
	puts("rev");

	if(msg_get.cmd == ADM_RVS)		//管理员修改
	{
		/*******检查修改员工是否存在*******/
		sprintf(sql,"select * from stuff where number='%s'",msg_get.msg);
		if(sqlite3_get_table(db,sql,&rep,&n_row,NULL,&errmsg))
		{
			puts(errmsg);
			return;
		}

		if(n_row)		//有此员工号
		{
			strcpy(number,msg_get.msg);		//保存修改目标
			msg_send.cmd = OK;
			send(clientfd,(void*)&msg_send,sizeof(msg_send),0);

			recvnum = recv(clientfd,(void *)&msg_get,sizeof(msg_get),0);	//接收修改内容
			if(recvnum < 0)
			{
				puts("fail to recv");
				return ;
			}
			if(recvnum == 0)
			{
				puts("client exit");
				close(clientfd);
				return ;
			}
		}else   		//无此员工号
		{	
			msg_send.cmd = NO_USER;
			send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
			sqlite3_free_table(rep);
			return;
		}
		sqlite3_free_table(rep);
		/*******检查结束*******/
	}
	else 				//普通用户修改
		strcpy(number,logininfo.number);		//保存修改目标
								
	sprintf(sql,"update stuff set %s%s%swhere number='%s'",\
			revworda[msg_get.cmd - RVS_PWD],msg_get.msg,\
			revwordb[msg_get.cmd - RVS_PWD],number);		//修改
	sqlite3_exec(db,sql,NULL,NULL,&errmsg);

	msg_send.cmd = OK;
	send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
}

void add_func()			//添加函数
{
	struct ADD_USER add;
	puts("add");
	/*******检查添加员工是否存在*******/
	sprintf(sql,"select * from stuff where number='%s'",msg_get.msg);
	if(sqlite3_get_table(db,sql,&rep,&n_row,NULL,&errmsg))
	{
		puts(errmsg);
		return;
	}

	if(n_row)		//有此员工号
	{
		msg_send.cmd = REPEAT;
		send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
	}
	else   		//无此员工号
	{
		msg_send.cmd = OK;
		send(clientfd,(void*)&msg_send,sizeof(msg_send),0);

		recvnum = recv(clientfd,(void *)&add,sizeof(add),0);	//接收新增员工全部信息结构体
		if(recvnum < 0)
		{
			puts("fail to recv");
			return ;
		}
		if(recvnum == 0)
		{
			puts("client exit");
			close(clientfd);
			return ;
		}

		sprintf(sql,"insert into stuff values('%s','%s',%d,'%s',%d,'%s','%s',%ld)"\
			,msg_get.msg,add.password,add.power,add.name,add.sex,add.addr,add.phone,add.money);
		sqlite3_exec(db,sql,NULL,NULL,&errmsg);					//添加员工
		msg_send.cmd = OK;
		send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
	}
	sqlite3_free_table(rep);
	/*******检查结束*******/
}

void del_func()			//删除函数
{
	puts("del");
	/*******检查删除员工是否存在*******/
	sprintf(sql,"select * from stuff where number='%s'",msg_get.msg);
	if(sqlite3_get_table(db,sql,&rep,&n_row,NULL,&errmsg))
	{
		puts(errmsg);
		return;
	}

	if(n_row)		//有此员工号
	{
		sprintf(sql,"delete from stuff where number='%s'",msg_get.msg);
		sqlite3_exec(db,sql,NULL,NULL,&errmsg);			//删除员工
		msg_send.cmd = OK;

	}else   		//无此员工号
		msg_send.cmd = NO_USER;

	send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
	sqlite3_free_table(rep);
	/*******检查结束*******/
}

void list_func()		//列举函数
{
	int i = 1;
	puts("list");
	
	sprintf(sql,"select * from stuff");		//调出全部员工信息
	if(sqlite3_get_table(db,sql,&rep,&n_row,NULL,&errmsg))
	{
		puts(errmsg);
		return;
	}
	msg_send.cmd = ERROR;					//命令码设为error
	sprintf(msg_send.msg,"员工编号  权限");
	send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
	usleep(3000);
	
	while(i < n_row)
	{
		sprintf(msg_send.msg,"  %-8s%s",rep[i * SQ_NUM],*rep[i * SQ_NUM + SQ_POWER] == '1' ? "管理员" : "普通");
		send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
		usleep(3000);
		i++; 
	}

	sprintf(msg_send.msg,"  %-8s%s\n",rep[i * SQ_NUM],*rep[i * SQ_NUM + SQ_POWER] == '1' ? "管理员" : "普通");
	msg_send.cmd = OK;						//最后一条信息命令码设为ok
	send(clientfd,(void*)&msg_send,sizeof(msg_send),0);
	sqlite3_free_table(rep);
}
